/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFPDC
  \brief for Proton DCs, constructed in Japan and reused by BUAA. NOTE that this
  serves as an abstract base class for class ETFPDCL and ETFPDCR. So DO NOT try
  instantiating it.
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-11-09
  \date 2021-11-23 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-11-09   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <cstring>
#include <TClonesArray.h>
#include <TGraph.h>
#include "ETFPDC.h"
#include "ETFDetectorManager.h"
#include "ETFHPTDCChannel.h"
#include "ETFDCHit.h"
#include "ETFMath.h"
#include "ETFMsg.h"
#include "ETFVTrack.h"
#include "ETFParaManager.h"
#include "ETFYaml.h"

ClassImp(ETFPDC);

static const double DEGREE = ETFMath::DEGREE();

ETFPDC::ETFPDC(const char *name) : ETFDCTa(name){
  NL = 8;
  // pass user trig bound parameters //
  ETFParaManager *pm = ETFParaManager::Instance();
  const YAML::Node &trigBConfig = (*pm->GetMisPara())["pdcTrigB"];
  if(trigBConfig){
    fTrigLB = trigBConfig[0].as<double>();
    fTrigHB = trigBConfig[1].as<double>();
  } // end if
} // end ctor

ETFPDC::~ETFPDC(){}

// add the data channel to the detector
void ETFPDC::Assign(const ETFHPTDCChannel *ch){
  const int uid = ETFDetectorManager::Instance()->GetUID(ch->GetChannelId());
  if(fDetId != (uid & 0xFF)) ETFMsg::Error("ETFPDC", "Assign: not from this DC.");
  const DCType xy = uid>>8 & 0x1 ? DCType::kY : DCType::kX;
  const int wireId = NL*(uid>>9 & 0x1) + (uid>>10 & 0xF);
  AddHit(ch, wireId, xy);
} // end member function Assign

// add DC signal wires to fGDumb
void ETFPDC::ConstructGraph(){
  if(fGDumb->GetN()) return; // has called

  fGDumb->SetMarkerStyle(7); fGDumb->SetMarkerColor(15); // gray
  for(int i = 0; i < 2; i++) for(int j = 0; j < NL; j++){
    double p[3] = {20.*j-10.*i-65., 0., 10.*i};
    TransformToLabRef(p);
    fGDumb->SetPoint(i*NL+j, p[2], p[0]);
  } // end for over i
} // end member function ConstructGraph

/// \retval false: if obtained drift time out of range
/// NOTE that if trk has non-FitStatus::kUNFITTED FitStatus, this method
/// would do nothing, as drift distance only changes with drift time,
/// whose changes would ensure fFitStatus be set to FitStatus::kUNFITTED
bool ETFPDC::SetDriftDistance(ETFVTrack *trk){
  // drift distance already assigned
  if(trk->GetFitStatus() != FitStatus::kUNFITTED) return true;

  for(auto &p : trk->GetHits()){
    ETFDCHit *h = p.second;
    // TODO: user input configuration expected here to confine drift time range
    if(!ETFMath::Within(h->GetDriftTime(), -30., 750.)) return false; // false hit
    h->SetDriftDistance(SpaceTimeRelation(h->GetDriftTime()));
  } // end for over hits
  return true;
} // end member function SetDriftDistance
